﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WPFLoaders
{
    public class CircleSegment : UserControl
    {
        public static readonly DependencyProperty StartDegreeProperty =
            DependencyProperty.Register("StartDegree", typeof (double), typeof (CircleSegment), new PropertyMetadata(default(double), OnSettingsChanged));

        public double StartDegree
        {
            get { return (double) GetValue(StartDegreeProperty); }
            set { SetValue(StartDegreeProperty, value); }
        }

        public static readonly DependencyProperty EndDegreeProperty =
            DependencyProperty.Register("EndDegree", typeof(double), typeof(CircleSegment), new PropertyMetadata(default(double), OnSettingsChanged));

        public double EndDegree
        {
            get { return (double) GetValue(EndDegreeProperty); }
            set { SetValue(EndDegreeProperty, value); }
        }

        public static readonly DependencyProperty FillProperty =
            DependencyProperty.Register("Fill", typeof(Brush), typeof(CircleSegment), new PropertyMetadata(default(Brush), OnSettingsChanged));

        public Brush Fill
        {
            get { return (Brush) GetValue(FillProperty); }
            set { SetValue(FillProperty, value); }
        }

        public static readonly DependencyProperty RadiusProperty =
            DependencyProperty.Register("Radius", typeof (double), typeof (CircleSegment), new PropertyMetadata(default(double), OnSettingsChanged));

        public double Radius
        {
            get { return (double) GetValue(RadiusProperty); }
            set { SetValue(RadiusProperty, value); }
        }

        private static void OnSettingsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CircleSegment) d).RebuildRendering();
        }

        private void RebuildRendering()
        {
            Content = null;

            const double damnSmall = 0.00001;
            if (Radius < damnSmall || Diff(StartDegree, EndDegree) < damnSmall)
                return;

            var startPoint = GetPoint(StartDegree);
            var endPoint = GetPoint(EndDegree);
            var middle = new Point(Radius, Radius);

            var direction = (int)(StartDegree > EndDegree
                                           ? SweepDirection.Counterclockwise
                                           : SweepDirection.Clockwise);

            int isBig = Diff(EndDegree, StartDegree) > 180 ? 1 : 0;

            var data = string.Format("M{0} L{1} A{2},{2} 0 {5} {4} {3} Z", middle.Format(), startPoint.Format(), Radius, endPoint.Format(), direction, isBig);
            
            //const double barelyVisible = 20;
            //if (EndDegree - StartDegree < barelyVisible)
            //    data = string.Format("M{0} L {1} L {2} Z", middle.Format(), startPoint.Format(), endPoint.Format());
            
            var path = new Path
                {
                    Width = Radius * 2,
                    Height = Radius * 2,
                    Data = Geometry.Parse(data),
                    Fill = Fill,
                };

            Content = path;
        }

        private double Diff(double startDegree, double endDegree)
        {
            return Math.Abs(startDegree - endDegree);
        }

        private Point GetPoint(double degrees)
        {
            var radians = Math.PI * (degrees/180);
            var normalized = new Point(Math.Cos(radians), Math.Sin(radians));

            const int decimals = 2;
            return new Point(
                    Math.Round(normalized.X * Radius, decimals) + Radius, 
                    Math.Round(normalized.Y * Radius, decimals) + Radius
                    );
        }
    }

    public static class PointExtensions
    {
        public static string Format(this Point p)
        {
            return p.X + "," + p.Y;
        }
    }
}
